package com.ai.dmc.index.dao.jotm.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import javax.transaction.UserTransaction;

import org.apache.ibatis.session.SqlSession;
import org.springframework.transaction.jta.JtaTransactionManager;

import com.ai.dmc.index.dao.base.IBaseDao;
import com.ai.dmc.index.dao.base.impl.BaseDaoImpl;
import com.ai.dmc.index.dao.jotm.dao.IBaseMDao;

/**
 * Title： Description：多数据源Dao接口实现类 Copyright：Copyright (c) 2009 Company：亚信科技（中国）有限公司
 * 
 * @author zlb, 2016年1月9日
 * @version 1.0
 */
public class BaseMDaoImpl implements IBaseMDao {

	private static ResourceBundle resources;

	private JtaTransactionManager transactionManager;

	private IBaseDao baseDao;

	public IBaseDao getBaseDao() {
		return baseDao;
	}

	public void setBaseDao(IBaseDao baseDao) {
		this.baseDao = baseDao;
	}

	static {
		resources = ResourceBundle.getBundle("config/mybaties");
	}

	/**
	 * rpt_web SqlSession
	 */
	private SqlSession rptWebSession;

	/**
	 * rpt_web DataSource key
	 */
	private String rptWebSrcKey;

	/**
	 * rpt_data SqlSession
	 */
	private SqlSession rptDataSession;

	/**
	 * rpt_data DataSource key
	 */
	private String rptDataSrcKey;

	/**
	 * idx_web SqlSession
	 */
	private SqlSession idxWebSession;

	/**
	 * idx_web DataSource key
	 */
	private String idxWebSrcKey;

	/**
	 * idx_data SqlSession
	 */
	private SqlSession idxDataSession;

	/**
	 * idx_data DataSource key
	 */
	private String idxDataSrcKey;
	
	/**
	 * map_data DataSource key
	 */
	private String mapDataSrcKey;
	
	private SqlSession  mapDataSession;

	/**
	 * default DataSource key
	 */
	private String defaultSrcKey;

	public JtaTransactionManager getTransactionManager() {
		return transactionManager;
	}

	public void setTransactionManager(JtaTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}

	public SqlSession getRptWebSession() {
		return rptWebSession;
	}

	public void setRptWebSession(SqlSession rptWebSession) {
		this.rptWebSession = rptWebSession;
	}

	public String getRptWebSrcKey() {
		return rptWebSrcKey;
	}

	public void setRptWebSrcKey(String rptWebSrcKey) {
		this.rptWebSrcKey = rptWebSrcKey;
	}

	public SqlSession getRptDataSession() {
		return rptDataSession;
	}

	public void setRptDataSession(SqlSession rptDataSession) {
		this.rptDataSession = rptDataSession;
	}

	public String getRptDataSrcKey() {
		return rptDataSrcKey;
	}

	public void setRptDataSrcKey(String rptDataSrcKey) {
		this.rptDataSrcKey = rptDataSrcKey;
	}

	public SqlSession getIdxWebSession() {
		return idxWebSession;
	}

	public void setIdxWebSession(SqlSession idxWebSession) {
		this.idxWebSession = idxWebSession;
	}

	public String getIdxWebSrcKey() {
		return idxWebSrcKey;
	}

	public void setIdxWebSrcKey(String idxWebSrcKey) {
		this.idxWebSrcKey = idxWebSrcKey;
	}

	public SqlSession getIdxDataSession() {
		return idxDataSession;
	}

	public void setIdxDataSession(SqlSession idxDataSession) {
		this.idxDataSession = idxDataSession;
	}

	public String getIdxDataSrcKey() {
		return idxDataSrcKey;
	}

	public void setIdxDataSrcKey(String idxDataSrcKey) {
		this.idxDataSrcKey = idxDataSrcKey;
	}
	
	public void setMapDataSrcKey(String mapDataSrcKey) {
		this.mapDataSrcKey = mapDataSrcKey;
	}
	
	public SqlSession getMapDataSession() {
		return mapDataSession;
	}

	public void setMapDataSession(SqlSession mapDataSession) {
		this.mapDataSession = mapDataSession;
	}

	public String getMapDataSrcKey() {
		return mapDataSrcKey;
	}

	
	

	public String getDefaultSrcKey() {
		return defaultSrcKey;
	}

	public void setDefaultSrcKey(String defaultSrcKey) {
		this.defaultSrcKey = defaultSrcKey;
	}

	/**
	 * 获取sqlSession
	 * 
	 * @param sqlId
	 * @return
	 */
	private SqlSession getSqlSession(String sqlId) {
		String srcKey = null;

		try {
			srcKey = resources.getString(sqlId);
		} catch (Exception e) {

		}

		if (null == srcKey) {
			srcKey = defaultSrcKey;
		}

		if (rptDataSrcKey.equals(srcKey)) {
			return rptDataSession;
		} else if (rptWebSrcKey.equals(srcKey)) {
			return rptWebSession;
		} else if (idxWebSrcKey.equals(srcKey)) {
			return idxWebSession;
		} else if (idxDataSrcKey.equals(srcKey)) {
			return idxDataSession;
		} else if (mapDataSrcKey.equals(srcKey)) {
			return mapDataSession;
		} else {
			throw new NullPointerException("SqlSession null: " + sqlId);
		}
	}

	@Override
	public Object[] queryForObject(int id, String... sqlIds) {
		Object[] results = new Object[sqlIds.length];
		for (int i = 0; i < sqlIds.length; i++) {
			baseDao.setSqlSession(getSqlSession(sqlIds[i]));
			results[i] = baseDao.queryForObject(sqlIds[i], id);
		}
		return results;
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T> T[] queryForObject(int id, Class<T> cls, String... sqlIds) {
		T[] results = (T[]) new Object[sqlIds.length];
		for (int i = 0; i < sqlIds.length; i++) {
			baseDao.setSqlSession(getSqlSession(sqlIds[i]));
			results[i] = baseDao.queryForObject(sqlIds[i], id, cls);
		}
		return results;
	}

	@Override
	public Object[] queryForObject(Map<String, String> params, String... sqlIds) {
		Object[] results = new Object[sqlIds.length];
		for (int i = 0; i < sqlIds.length; i++) {
			baseDao.setSqlSession(getSqlSession(sqlIds[i]));
			results[i] = baseDao.queryForObject(sqlIds[i], params);
		}
		return results;
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T> T[] queryForObject(Map<String, String> params, Class<T> cls, String... sqlIds) {
		T[] results = (T[]) new Object[sqlIds.length];
		for (int i = 0; i < sqlIds.length; i++) {
			baseDao.setSqlSession(getSqlSession(sqlIds[i]));
			results[i] = baseDao.queryForObject(sqlIds[i], params, cls);
		}
		return results;
	}

	@Override
	public int[] getTotalCount(Map<String, String> params, String... sqlIds) {
		int[] results = new int[sqlIds.length];
		for (int i = 0; i < sqlIds.length; i++) {
			baseDao.setSqlSession(getSqlSession(sqlIds[i]));
			results[i] = baseDao.getTotalCount(sqlIds[i], params);
		}
		return results;
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T> List<T>[] queryForList(Map<String, String> params, Class<T> cls, String... sqlIds) {
		List<T>[] results = new ArrayList[sqlIds.length];
		for (int i = 0; i < sqlIds.length; i++) {
			baseDao.setSqlSession(getSqlSession(sqlIds[i]));
			results[i] = baseDao.queryForList(sqlIds[i], params, cls);
		}
		return results;
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Map<String, String>>[] queryForList(Map<String, String> params, String... sqlIds) {
		List<Map<String, String>>[] results = new ArrayList[sqlIds.length];
		for (int i = 0; i < sqlIds.length; i++) {
			baseDao.setSqlSession(getSqlSession(sqlIds[i]));
			// 单独改造，满足根据 table&方法 共同决定切换数据源
			results[i] = baseDao.queryForList(sqlIds[i], params);
		}
		return results;
	}

	@Override
	public int[] update(Object object, String... sqlIds) {
		int[] results = new int[sqlIds.length];
		UserTransaction transaction = this.transactionManager.getUserTransaction();
		try {
			transaction.begin();
			for (int i = 0; i < sqlIds.length; i++) {
				baseDao.setSqlSession(getSqlSession(sqlIds[i]));
				results[i] = baseDao.update(sqlIds[i], object);
			}
			transaction.commit();
		} catch (Exception e1) {
			try {
				transaction.rollback();
			} catch (Exception e2) {
				throw new RuntimeException(e2);
			}
			throw new RuntimeException(e1);
		}
		return results;
	}

	@Override
	public int[] insert(Object object, String... sqlIds) {
		int[] results = new int[sqlIds.length];
		UserTransaction transaction = this.transactionManager.getUserTransaction();
		try {
			transaction.begin();
			for (int i = 0; i < sqlIds.length; i++) {
				baseDao.setSqlSession(getSqlSession(sqlIds[i]));
				results[i] = baseDao.insert(sqlIds[i], object);
			}
			transaction.commit();
		} catch (Exception e1) {
			try {
				transaction.rollback();
			} catch (Exception e2) {
				throw new RuntimeException(e2);
			}
			throw new RuntimeException(e1);
		}
		return results;
	}

	@Override
	public int[] delete(int id, String... sqlIds) {
		int[] results = new int[sqlIds.length];
		UserTransaction transaction = this.transactionManager.getUserTransaction();
		try {
			transaction.begin();
			for (int i = 0; i < sqlIds.length; i++) {
				baseDao.setSqlSession(getSqlSession(sqlIds[i]));
				results[i] = baseDao.delete(sqlIds[i], id);
			}
			transaction.commit();
		} catch (Exception e1) {
			try {
				transaction.rollback();
			} catch (Exception e2) {
				throw new RuntimeException(e2);
			}
			throw new RuntimeException(e1);
		}
		return results;
	}

	@Override
	public int[] delete(Map<String, String> params, String... sqlIds) {
		int[] results = new int[sqlIds.length];
		UserTransaction transaction = this.transactionManager.getUserTransaction();
		try {
			transaction.begin();
			for (int i = 0; i < sqlIds.length; i++) {
				baseDao.setSqlSession(getSqlSession(sqlIds[i]));
				results[i] = baseDao.delete(sqlIds[i], params);
			}
			transaction.commit();
		} catch (Exception e1) {
			try {
				transaction.rollback();
			} catch (Exception e2) {
				throw new RuntimeException(e2);
			}
			throw new RuntimeException(e1);
		}
		return results;
	}

	public Object queryForObject(String sqlId, int id) {
		baseDao.setSqlSession(getSqlSession(sqlId));
		return baseDao.queryForObject(sqlId, id);
	}

	public <T> T queryForObject(String sqlId, int id, Class<T> cls) {
		baseDao.setSqlSession(getSqlSession(sqlId));
		return baseDao.queryForObject(sqlId, id, cls);
	}

	public Object queryForObject(String sqlId, Map<String, String> params) {
		baseDao.setSqlSession(getSqlSession(sqlId));
		return baseDao.queryForObject(sqlId, params);
	}

	public <T> T queryForObject(String sqlId, Map<String, String> params, Class<T> cls) {
		baseDao.setSqlSession(getSqlSession(sqlId));
		return baseDao.queryForObject(sqlId, params, cls);
	}

	public int getTotalCount(String sqlId, Map<String, String> params) {
		baseDao.setSqlSession(getSqlSession(sqlId));
		return baseDao.getTotalCount(sqlId, params);
	}

	public <T> List<T> queryForList(String sqlId, Map<String, String> params, Class<T> cls) {
		baseDao.setSqlSession(getSqlSession(sqlId));
		return baseDao.queryForList(sqlId, params, cls);
	}

	public List<Map<String, String>> queryForList(String sqlId, Map<String, String> params) {
		baseDao.setSqlSession(getSqlSession(sqlId));
		// 单独改造，满足根据 table&方法 共同决定切换数据源
		return baseDao.queryForList(sqlId, params);
	}
	 /**
	  * 查询分页列表
	  * 
	  * @param sqlId
	  *            脚本编号
	  * @param params
	  *            参数
	  * @return 列表
	  */
	 public List<Map<String, String>> queryForPageList(String sqlId,
	         Map<String, String> param) {
	     int pageSize = Integer.parseInt(param.get("pageSize").toString());
	     int currentPage = Integer.parseInt(param.get("currentPage").toString());
	     if (currentPage <= 0) {
	         currentPage = 1;
	     }
	     
	     param.remove("pageSize");
	     param.remove("currentPage");
	     Map<String, String> params = new HashMap<String, String>();
	     params.putAll(param);
	     params.put("startPageNum", Integer.toString((currentPage - 1) * pageSize));
	     params.put("pageSize", Integer.toString(pageSize));
		 baseDao.setSqlSession(getSqlSession(sqlId));
		 // 单独改造，满足根据 table&方法 共同决定切换数据源
		 return baseDao.queryForList(sqlId, params);
	    }	 

	/**
	 * 查询列表
	 * 
	 * @param sqlId
	 *            脚本编号
	 * @param params
	 *            参数
	 * @return 列表
	 */
	public List<Map<String, Object>> queryForListByObjectMap(String sqlId, Map<String, Object> param) {
		baseDao.setSqlSession(getSqlSession(sqlId));
		return baseDao.queryForListByObjectMap(sqlId, param);
	}

	public int update(String sqlId, Object object) {
		int results = -1;
		UserTransaction transaction = this.transactionManager.getUserTransaction();
		try {
			transaction.begin();
			baseDao.setSqlSession(getSqlSession(sqlId));
			results = baseDao.update(sqlId, object);
			transaction.commit();
		} catch (Exception e1) {
			try {
				transaction.rollback();
			} catch (Exception e2) {
				throw new RuntimeException(e2);
			}
			throw new RuntimeException(e1);
		}
		return results;
	}

	public int insert(String sqlId, Object object) {
		int results = -1;
		UserTransaction transaction = this.transactionManager.getUserTransaction();
		try {
			transaction.begin();
			baseDao.setSqlSession(getSqlSession(sqlId));
			results = baseDao.insert(sqlId, object);
			transaction.commit();
		} catch (Exception e1) {
			try {
				transaction.rollback();
			} catch (Exception e2) {
				throw new RuntimeException(e2);
			}
			throw new RuntimeException(e1);
		}
		return results;
	}

	public int delete(String sqlId, int id) {
		int results = -1;
		UserTransaction transaction = this.transactionManager.getUserTransaction();
		try {
			transaction.begin();
			baseDao.setSqlSession(getSqlSession(sqlId));
			results = baseDao.delete(sqlId, id);
			transaction.commit();
		} catch (Exception e1) {
			try {
				transaction.rollback();
			} catch (Exception e2) {
				throw new RuntimeException(e2);
			}
			throw new RuntimeException(e1);
		}
		return results;
	}

	public int delete(String sqlId, Map<String, String> params) {
		int results = -1;
		UserTransaction transaction = this.transactionManager.getUserTransaction();
		try {
			transaction.begin();
			baseDao.setSqlSession(getSqlSession(sqlId));
			results = baseDao.delete(sqlId, params);
			transaction.commit();
		} catch (Exception e1) {
			try {
				transaction.rollback();
			} catch (Exception e2) {
				throw new RuntimeException(e2);
			}
			throw new RuntimeException(e1);
		}
		return results;
	}

	@Override
	public int[] executeDeleteInsert(String delSqlId, String insertSqlId, Map<String, String> params) {
		UserTransaction transaction = this.transactionManager.getUserTransaction();
		try {
			transaction.begin();
			baseDao.setSqlSession(getSqlSession(delSqlId));
			baseDao.delete(delSqlId, params);
			baseDao.setSqlSession(getSqlSession(insertSqlId));
			baseDao.insert(insertSqlId, params);
			transaction.commit();
		} catch (Exception e1) {
			try {
				transaction.rollback();
			} catch (Exception e2) {
				throw new RuntimeException(e2);
			}
			throw new RuntimeException(e1);
		}
		return null;
	}
	@Override
	public int[] executeDeleteInsertDiffParam(String delSqlId, String insertSqlId, Map<String, String> delParam,List<Map<String,String>> insertParam) {
		UserTransaction transaction = this.transactionManager.getUserTransaction();
		try {
			transaction.begin();
			baseDao.setSqlSession(getSqlSession(delSqlId));
			baseDao.delete(delSqlId, delParam);
			baseDao.setSqlSession(getSqlSession(insertSqlId));
			baseDao.insert(insertSqlId, insertParam);
			transaction.commit();
		} catch (Exception e1) {
			try {
				transaction.rollback();
			} catch (Exception e2) {
				throw new RuntimeException(e2);
			}
			throw new RuntimeException(e1);
		}
		return null;
	}

    @Override
    public List<Map<String, String>> queryForListByObjectMap2(String sqlId, Map<String, Object> param) {
        baseDao.setSqlSession(getSqlSession(sqlId));
        return baseDao.queryForListByObjectMap2(sqlId, param);
    }

    @Override
    public List<Map<String, String>> queryForPageListByObjectMap2(String sqlId, Map<String, Object> param) {
        baseDao.setSqlSession(getSqlSession(sqlId));
        return baseDao.queryForPageListByObjectMap2(sqlId, param);
    }

    @Override
    public List<Map<String, Object>> queryForPageListByObjectMap(String sqlId, Map<String, Object> param) {
        baseDao.setSqlSession(getSqlSession(sqlId));
        return baseDao.queryForPageListByObjectMap(sqlId, param);
    }

    @Override
    public int getTotalCountByObjectMap(String sqlId, Map<String, Object> params) {
        baseDao.setSqlSession(getSqlSession(sqlId));
        return baseDao.getTotalCountByObjectMap(sqlId, params);
    }

    @Override
    public Object queryForObjectByObjectMap(String sqlId, Map<String, Object> params) {
        baseDao.setSqlSession(getSqlSession(sqlId));
        return baseDao.queryForObjectByObjectMap(sqlId, params);
    }
}